//
// Created by root on 19-7-29.
//

#include "hook_parse_app.h"
#include "AndHook.h"
#include "log_utils.h"
#include "file_utils.h"
#include "method_utils.h"

#define TAG "ParseBaseApplication"

static jmethodID old_method= nullptr;

//[class android.content.pm.PackageParser$Package, class android.content.res.Resources,
// interface org.xmlpull.v1.XmlPullParser, interface android.util.AttributeSet, int, class [Ljava.lang.String;]
bool my_parse_base_app(JNIEnv *env,jobject instance,
        jobject owner,jobject res,jobject parser,jobject attrSet,int flags,jobjectArray outError){
    jclass package_class=env->FindClass("android/content/pm/PackageParser$Package");

    if(!package_class) {
        LOGE("fail to find package_class\n");
        return true;
    }

    jfieldID package_name_field=env->GetFieldID(package_class,"packageName","Ljava/lang/String;");
    jstring package_name_=(jstring)env->GetObjectField(owner,package_name_field);
    const char* c_package_name=env->GetStringUTFChars(package_name_, nullptr);
    LOGD("before parse base app:%s\n",c_package_name);

    if(keep_alive_contains(c_package_name)){//需要保活处理

        jclass app_info_class=env->FindClass("android/content/pm/ApplicationInfo");
        jfieldID app_info_field=env->GetFieldID(package_class,"applicationInfo","Landroid/content/pm/ApplicationInfo;");
        jobject app_info=env->GetObjectField(owner,app_info_field);
        jfieldID ai_flag_field=env->GetFieldID(app_info_class,"flags","I");
        int ai_flags=env->GetIntField(app_info,ai_flag_field);
        //persistent保活
        int FLAG_PERSISTENT = 1<<3;
        int FLAG_SYSTEM = 1<<0;
        ai_flags|=FLAG_SYSTEM;
        ai_flags|=FLAG_PERSISTENT;
        env->SetIntField(app_info,ai_flag_field,ai_flags);
        env->SetObjectField(owner,app_info_field,app_info);

        LOGD("FLAG_PERSISTENT=%d has been added into app:%s\n",FLAG_PERSISTENT,c_package_name);
    }

    bool parse_ret=env->CallBooleanMethod(instance,old_method,
            owner,res,parser,attrSet,flags,outError);
    env->ReleaseStringUTFChars(package_name_,c_package_name);
    return parse_ret;
}

void hook_parse_base_app(JNIEnv *env) {
    if(old_method)
        return;
    jclass package_parser_class=env->FindClass("android/content/pm/PackageParser");
    if(!package_parser_class){
        LOGE("fail to find package_parser_class\n");
        return;
    }
    jmethodID parse_base_app=get_method_by_name(env,package_parser_class,"parseBaseApplication");
    if(!parse_base_app)
        return;
    AKJavaHookMethodV(env,parse_base_app,
            reinterpret_cast<void*>(my_parse_base_app),&old_method);
    /*AKJavaHookMethod(env,package_parser_class,
            "parseBaseApplication",
            "(Landroid/content/pm/PackageParser$Package;Landroid/content/res/Resources;Lorg/xmlpull/v1/XmlPullParser;Landroid/util/AttributeSet;I[Ljava/lang/String;)Z",
            reinterpret_cast<void*>(my_parse_base_app),&old_method);*/
    LOGD("old_method:%p\n",old_method);
}
